package com.gitee.wsl.transform.escape

import kotlin.jvm.JvmOverloads
import kotlin.jvm.JvmStatic

object EscapeReplacer {

        /**
         * 为给定的字符(\t,\r,\n,\',\"及定义的escapeChar)串增加指定的转义符，并返回新产生的新串
         * @param str 需要增加转义符的字符串
         * @param escapeChar 转义符
         * @return 新串
         */
        /**
         * 相当于调用 add(str, '\\')
         */
        @JvmOverloads
        fun add(str: String, escapeChar: Char = '\\'): String {

            val len = str.length
            val sb = CharArray(2 * len + 2) //str.length=1
            var j = 0
            for (i in 0 until len) {
                val ch = str[i]
                when (ch) {
                    '\t' -> {
                        sb[j++] = escapeChar
                        sb[j++] = 't'
                    }

                    '\r' -> {
                        sb[j++] = escapeChar
                        sb[j++] = 'r'
                    }

                    '\n' -> {
                        sb[j++] = escapeChar
                        sb[j++] = 'n'
                    }

                    '\'' -> {
                        sb[j++] = escapeChar
                        sb[j++] = '\''
                    }

                    '\"' -> {
                        sb[j++] = escapeChar
                        sb[j++] = '\"'
                    }

                    else -> {
                        if (ch == escapeChar) {
                            sb[j++] = escapeChar
                        }
                        sb[j++] = ch
                    }
                }
            }
            return sb.concatToString(0, 0 + j)
        }

        /**
         * 为给定的字符串增加指定的转义符，并返回新产生的新串
         *
         * @param str 需要增加转义符的字符串
         * @param escapedChars 需要被转义的字符
         * @param escapeChar 转义符
         * @return 新串
         */
        /**
         * 为给定的字符串增加指定的转义符，并返回新产生的新串
         *
         * @param str 需要增加转义符的字符串
         * @param escapedChars 需要被转义的字符
         * @return 新串
         */
        @JvmOverloads
        fun add(str: String, escapedChars: String?, escapeChar: Char = '\\'): String {

            val len = str.length
            val sb = CharArray(2 * len + 2) //str.length=1
            var j = 0
            for (i in 0 until len) {
                val ch = str[i]
                when (ch) {
                    '\t' -> {
                        sb[j++] = escapeChar
                        sb[j++] = 't'
                    }

                    '\r' -> {
                        sb[j++] = escapeChar
                        sb[j++] = 'r'
                    }

                    '\n' -> {
                        sb[j++] = escapeChar
                        sb[j++] = 'n'
                    }

                    '\'' -> {
                        sb[j++] = escapeChar
                        sb[j++] = '\''
                    }

                    '\"' -> {
                        sb[j++] = escapeChar
                        sb[j++] = '\"'
                    }

                    else -> {
                        if ((ch == escapeChar) ||
                            (escapedChars != null && escapedChars.indexOf(ch) >= 0)
                        ) sb[j++] = escapeChar
                        sb[j++] = ch
                    }
                }
            }
            return sb.concatToString(0, 0 + j)
        }

        fun addEscAndQuote(str: String, escapedChars: String?, escapeChar: Char): String {
            return addEscAndQuote(str, true, escapedChars, escapeChar)
        }

        fun addEscAndQuote(
            str: String,
            ifDblQuote: Boolean,
            escapedChars: String?,
            escapeChar: Char,
        ): String {

            val len = str.length
            val sb = CharArray(2 * len + 2) //str.length=1
            sb[0] = if (ifDblQuote) '\"' else '\''
            var j = 1
            for (i in 0 until len) {
                val ch = str[i]
                when (ch) {
                    '\t' -> {
                        sb[j++] = escapeChar
                        sb[j++] = 't'
                    }

                    '\r' -> {
                        sb[j++] = escapeChar
                        sb[j++] = 'r'
                    }

                    '\n' -> {
                        sb[j++] = escapeChar
                        sb[j++] = 'n'
                    }

                    '\'' -> {
                        if (!ifDblQuote) sb[j++] = escapeChar
                        sb[j++] = '\''
                    }

                    '\"' -> {
                        if (ifDblQuote) sb[j++] = escapeChar
                        sb[j++] = '\"'
                    }

                    else -> {
                        if ((ch == escapeChar) ||
                            (escapedChars != null && escapedChars.indexOf(ch) >= 0)
                        ) sb[j++] = escapeChar
                        sb[j++] = ch
                    }
                }
            }
            sb[j++] = if (ifDblQuote) '\"' else '\''
            return sb.concatToString(0, 0 + j)
        }


        /**
         * 将指定的字符串移去指定转义符，并返回新产生的新串
         *
         * @param str 需要移去转义符的字符串
         * @param escapeChar 转义字符
         * @return 原串移去转义符后的新串
         */
        /**
         * 相当于调用 remove( str, '\\')
         */
        @JvmOverloads
        fun remove(str: String, escapeChar: Char = '\\'): String {

            val len = str.length
            if (len == 0) return str
            val sb = CharArray(len)
            var i = 0
            var j = 0
            var ch = str[i]
            while (i < len) {
                ch = str[i]
                if (ch == escapeChar) {
                    i++
                    if (i == len) break
                    ch = str[i]
                    when (ch) {
                        't' -> sb[j++] = '\t'
                        'r' -> sb[j++] = '\r'
                        'n' -> sb[j++] = '\n'
                        else -> sb[j++] = ch
                    }
                } else sb[j++] = ch
                i++
            }
            return sb.concatToString(0, 0 + j)
        }

        /**
         * 将使用旧转义符的字符串变换使用新转义符的字符串
         * @param str 需要变换转义符的串
         * @param oldEscapeChar 旧转义符
         * @param newEscapeChar 新转义符
         * @return 变换后的新串
         */
        fun change(str: String, oldEscapeChar: Char, newEscapeChar: Char): String {

            val len = str.length
            if (len == 0) return str
            val sb = CharArray(len)
            var i = 0
            while (i < len) {
                if (str[i] == oldEscapeChar) {
                    sb[i++] = newEscapeChar
                    if (i < len) sb[i] = str[i]
                } else sb[i] = str[i]
                i++
            }
            return sb.concatToString()
        }

        /**
         * 相当于调用 addEscapeAndQuote(str, true, '\\')
         */
        fun addEscAndQuote(str: String, escapeChar: Char): String {
            return addEscAndQuote(str, true, escapeChar)
        }

        /**
         * 为给定的字符串增加指定的转义符，且前后补上引号，并返回新产生的新串
         *
         * @param str 需要增加转义符的字符串
         * @param ifDblQuote 为true时加上双引号，否则加上单引号
         * @param escapeChar 转义符
         * @return 新串
         */
        /**
         * 相当于调用 addEscAndQuote(str, true, '\\')
         */
        /**
         * 相当于调用 addEscAndQuote(str, ifDblQuote, '\\')
         */
        @JvmOverloads
        fun addEscAndQuote(
            str: String,
            ifDblQuote: Boolean = true,
            escapeChar: Char = '\\',
        ): String {
            val len = str.length
            val sb = CharArray(2 * len + 2) //str.length=1
            sb[0] = if (ifDblQuote) '\"' else '\''
            var j = 1
            for (i in 0 until len) {
                val ch = str[i]
                when (ch) {
                    '\t' -> {
                        sb[j++] = escapeChar
                        sb[j++] = 't'
                    }

                    '\r' -> {
                        sb[j++] = escapeChar
                        sb[j++] = 'r'
                    }

                    '\n' -> {
                        sb[j++] = escapeChar
                        sb[j++] = 'n'
                    }

                    '\'' -> {
                        if (!ifDblQuote) sb[j++] = escapeChar
                        sb[j++] = '\''
                    }

                    '\"' -> {
                        if (ifDblQuote) sb[j++] = escapeChar
                        sb[j++] = '\"'
                    }

                    else -> {
                        if (ch == escapeChar) {
                            sb[j++] = escapeChar
                        }
                        sb[j++] = ch
                    }
                }
            }
            sb[j++] = if (ifDblQuote) '\"' else '\''
            return sb.concatToString(0, 0 + j)
        }

        /**
         * 使用excel标准添加双引号
         * @param str
         * @return
         */
        fun addExcelQuote(str: String?): String? {
            if (str == null) {
                return null
            }

            val len = str.length
            val sb = CharArray(2 * len + 2) //str.length=1
            sb[0] = '"'
            var j = 1
            for (i in 0 until len) {
                val ch = str[i]
                if (ch == '"') {
                    sb[j++] = '"'
                    sb[j++] = '"'
                } else {
                    sb[j++] = ch
                }
            }

            sb[j++] = '\"'
            return sb.concatToString(0, 0 + j)
        }

        /**
         * 将指定的字符串移去最外边的引号及指定转义符，并返回新产生的新串
         *
         * @param str 需要移去转义符的字符串
         * @param escapeChar 转义字符
         * @return 原串移去转义符后的新串
         */
        /**
         * 相当于调用 removeEscAndQuote( str, '\\')
         */
        @JvmOverloads
        fun removeEscAndQuote(str: String?, escapeChar: Char = '\\'): String? {
            if (str == null) return null

            var len = str.length
            if (len == 0) return str
            val sb = CharArray(len)
            var i = 0
            var j = 0
            var ch = str[i]

            if ((ch == '"' || ch == '\'') && str[len - 1] == ch) {
                i++
                len--
            }

            while (i < len) {
                ch = str[i]
                if (ch == escapeChar) {
                    i++
                    if (i == len) break
                    ch = str[i]
                    when (ch) {
                        't' -> sb[j++] = '\t'
                        'r' -> sb[j++] = '\r'
                        'n' -> sb[j++] = '\n'
                        else -> sb[j++] = ch
                    }
                } else {
                    sb[j++] = ch
                }
                i++
            }

            return sb.concatToString(0, 0 + j)
        }

}